package com.act.moudles.user.service.impl;

import com.act.components.UserComponent;
import com.act.constant.LoginTypeEnums;
import com.act.moudles.user.dao.MenuDao;
import com.act.moudles.user.entity.Menu;
import com.act.moudles.user.service.MenuService;
import com.act.utils.vueMenu.TreeSelect;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.apache.commons.lang3.StringUtils;
import java.util.*;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import org.springframework.util.CollectionUtils;

/**
 * 菜单权限表Service
 * @author monxz
 * @version 2023-02-06
 */
@Service
@Transactional(rollbackFor = Exception.class)
@Slf4j
public class MenuServiceImpl extends ServiceImpl<MenuDao, Menu> implements MenuService {

	@Resource
    private UserComponent userComponent;

	@Override
	public String  addMenu(Menu menu){
		//1. 去重验证
        String checkRes = checkUnion(menu);
        if(StringUtils.isNotEmpty(checkRes)){
            return checkRes;
        }
        //2.新增
		menu.setCreateBy(userComponent.getCurrentRealName(LoginTypeEnums.WEB.getType()));
		menu.setCreateTime(new Date());
        //3.查询父级数据
        Menu parentMenu = getById(menu.getParentId());
        if(parentMenu != null){
            menu.setParentIds((StringUtils.isEmpty(parentMenu.getParentIds())? "":parentMenu.getParentIds()+",")+parentMenu.getMenuId());
        }
        save(menu);
        return null;
	}

	@Override
	public String  updateMenu(Menu menu){
		//1. 去重验证
        String checkRes = checkUnion(menu);
        if(StringUtils.isNotEmpty(checkRes)){
            return checkRes;
        }
        //2.修改
		menu.setUpdateBy(userComponent.getCurrentRealName(LoginTypeEnums.WEB.getType()));
		menu.setUpdateTime(new Date());
        //3.查询父级数据
        Menu parentMenu = getById(menu.getParentId());
        if(parentMenu != null){
            menu.setParentIds((StringUtils.isEmpty(parentMenu.getParentIds())? "":parentMenu.getParentIds()+",")+parentMenu.getMenuId());
        }
        updateById(menu);
        return null;
	}

    @Override
    public List<Menu> buildMenuTree(Menu menu) {
	    //查询原始数据
        LambdaQueryWrapper<Menu> query = new LambdaQueryWrapper<>();
        query.like(StringUtils.isNotEmpty(menu.getMenuName()),Menu::getMenuName,menu.getMenuName());
        query.orderByAsc(Menu::getOrderNum);
	    List<Menu> menuList = list(query);
	    if(StringUtils.isNotEmpty(menu.getMenuName()) && !CollectionUtils.isEmpty(menuList)){
	        //如果查询时当前数据，则查询所有上级的数据
            Set<Long> parentIdList = new HashSet<>();
            for(Menu temp : menuList){
                if(StringUtils.isEmpty(temp.getParentIds())){
                    continue;
                }
                for(String tempParentId : temp.getParentIds().split(",")){
                    parentIdList.add(Long.parseLong(tempParentId));
                }
            }
            if(!CollectionUtils.isEmpty(parentIdList)){
                query.clear();
                query.in(Menu::getMenuId,parentIdList);
                query.orderByAsc(Menu::getOrderNum);
                List<Menu> parentMenuList =  list(query);
                menuList.addAll(parentMenuList);
            }
        }
//        menuList = menuList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new   TreeSet<>(Comparator.comparing(Menu :: getMenuId))), ArrayList::new));
        menuList.sort((o1,o2) -> o1.getOrderNum() - o2.getOrderNum());
        return getChildPerms(menuList,0L);
    }

    @Override
    public List<Menu> buildMenuChildren(List<Menu> menuList) {
        return getChildPerms(menuList,0L);
    }

    @Override
    public List<TreeSelect> buildTreeSelect(List<Menu> roleMenuList) {
        //0.构建用户存在的菜单树
        Map<Long,Integer> roleMenuMap = new HashMap<Long,Integer>(){{
            roleMenuList.forEach(o->{
                put(o.getMenuId(),1);
            });
        }};
	    //1查询所有的菜单树
        List<Menu>  allMenuList =  list();
        for(Menu menu : allMenuList){
            if(roleMenuMap.get(menu.getMenuId()) != null){
                menu.setHasChecked(true);
            }else {
                menu.setHasChecked(false);
            }
        }
        //2.构建children
        List<Menu>  menuTree = getChildPerms(allMenuList,0L);
        return menuTree.stream().map(TreeSelect::new).collect(Collectors.toList());

    }

    @Override
    public String removeMenu(Long menuId) {
	    LambdaQueryWrapper<Menu> query = new LambdaQueryWrapper<>();
        query.eq(Menu::getParentId,menuId);
        long count = count(query);
        if(count - 1L > 0L){
            return "存在子级菜单，不可删除";
        }
        removeById(menuId);
        return null;
    }


    /**
     * 根据父节点的ID获取所有子节点
     * @param list 分类表
     * @param parentId 传入的父节点ID
     * @return String
     */
    public List<Menu> getChildPerms(List<Menu> list, Long parentId) {
        List<Menu> returnList = new ArrayList<Menu>();
        for (Iterator<Menu> iterator = list.iterator(); iterator.hasNext();){
            Menu t = (Menu) iterator.next();
            // 一、根据传入的某个父节点ID,遍历该父节点的所有子节点
            if (t.getParentId() .equals( parentId))
            {
                recursionFn(list, t);
                returnList.add(t);
            }
        }
        return returnList;
    }

    /**
     * 递归列表
     *
     * @param list
     * @param t
     */
    private void recursionFn(List<Menu> list, Menu t){
        // 得到子节点列表
        List<Menu> childList = getChildList(list, t);
        t.setChildren(childList);
        for (Menu tChild : childList){
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }
    }

    /**
     * 得到子节点列表
     */
    private List<Menu> getChildList(List<Menu> list, Menu t){
        List<Menu> tlist = new ArrayList<Menu>();
        Iterator<Menu> it = list.iterator();
        while (it.hasNext()){
            Menu n = (Menu) it.next();
            if (n.getParentId() - t.getMenuId() == 0L){
                tlist.add(n);
            }
        }
        return tlist;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<Menu> list, Menu t)
    {
        return getChildList(list, t).size() > 0 ? true : false;
    }


    /**
     * 重复检验
     * @param menu
     * @return
     */
    private String checkUnion(Menu menu){
	    LambdaQueryWrapper<Menu>  query = new LambdaQueryWrapper<>();
        query.ne(menu.getMenuId() != null,Menu::getMenuId,menu.getMenuId());
        query.eq(Menu::getMenuName,menu.getMenuName());
        query.eq(Menu::getParentId,menu.getParentId());
		 long counts = count(query);
		 if(counts - 1L >= 0L){
		   return  "数据重复";
		 }
		 return null;
    }


}